package cn.com.cnxfs.relaxchat;

import android.content.ContentValues;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Base64;
import android.util.Log;
import android.view.MenuItem;
import android.widget.Toast;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.json.JSONArray;
import org.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {
    private String uid; //当前登录用户的id
    FragmentManager fragmentManager;
    FragmentTransaction fragmentTransaction;
    private Fragment nowFragment;
    private NewsFragment newsFragment = new NewsFragment();
    private ListFragment listFragment = new ListFragment();
    private MyFragment myFragment = new MyFragment();
    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = new BottomNavigationView.OnNavigationItemSelectedListener() {

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home: //我
                    if(nowFragment != myFragment){
                        fragmentTransaction = fragmentManager.beginTransaction(); //启动碎片切换事物
                        fragmentTransaction.replace(R.id.frameLayout, myFragment).commit(); //载入消息列表碎片
                        nowFragment = myFragment; //记录当前显示的碎片
                    }
                    return true;
                case R.id.navigation_dashboard: //好友列表
                    if(nowFragment != listFragment){
                        fragmentTransaction = fragmentManager.beginTransaction(); //启动碎片切换事物
                        fragmentTransaction.replace(R.id.frameLayout, listFragment).commit(); //载入消息列表碎片
                        nowFragment = listFragment; //记录当前显示的碎片
                    }
                    return true;
                case R.id.navigation_notifications: //消息
                    if(nowFragment != newsFragment){
                        fragmentTransaction = fragmentManager.beginTransaction(); //启动碎片切换事物
                        fragmentTransaction.replace(R.id.frameLayout, newsFragment).commit(); //载入消息列表碎片
                        nowFragment = newsFragment; //记录当前显示的碎片
                    }
                    return true;
            }
            return false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        SharedPreferences preferences = getSharedPreferences("db_login",MODE_PRIVATE);
        uid = preferences.getString("id","0"); //获取已登录的用户id
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        BottomNavigationView navigation = findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
        fragmentManager = getSupportFragmentManager(); //碎片管理器
        fragmentTransaction = fragmentManager.beginTransaction(); //启动碎片切换事物
        fragmentTransaction.replace(R.id.frameLayout, newsFragment).commit(); //载入消息列表碎片
        nowFragment = newsFragment; //记录当前显示的碎片
        fresh_friend(); //刷新好友列表
        mqttConnect(); //与MQTT服务器进行连接
        receiveOfflineMsg(); //接受离线消息
    }

    void fresh_friend(){  //刷新好友列表
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    FormBody.Builder params = new FormBody.Builder();
                    params.add("uid",uid); //添加url参数
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url(Api.url[0]+"/friend/list").post(params.build())
                            .build();
                    Response response = client.newCall(request).execute(); //执行发送指令
                    String responseData = response.body().string();
                    Log.d("主活动","收到好友列表"+responseData);
                    List<Friend> rcv = new ArrayList<>(); //保存收到的好友列表
                    JSONArray jsonArray = new JSONArray(responseData); //下面开始解析JSON
                    for(int i=0;i<jsonArray.length();i++){
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        Friend friend = new Friend();
                        friend.setId(Integer.parseInt(jsonObject.getString("id"))); //服务器数据库中这一行的id
                        friend.setFriend(Integer.parseInt(jsonObject.getString("friend"))); //好友的ID
                        friend.setNickname(jsonObject.getString("nickname"));
                        //state此时无法判断
                        rcv.add(friend);
                    }
                    //下面去更新本地数据库中的好友列表
                    MyDatabaseHelper databaseHelper = new MyDatabaseHelper(MainActivity.this, "database.db", null, 1); //打开本地数据库
                    SQLiteDatabase db = databaseHelper.getWritableDatabase();
                    db.delete("friend", "", null); //清空本地friend数据表
                    ContentValues values = new ContentValues(); //要添加到数据库中的数据
                    for(Friend friend : rcv) {
                        values.put("id", friend.getId()); //在服务器friend表中的id
                        values.put("friend", friend.getFriend()); //好友的uid
                        values.put("nickname", friend.getNickname());
                        values.put("state", 1); //默认没有未读消息
                        db.insert("friend", null, values);
                        values.clear();
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this,"获取好友列表失败！请检查网络连接！",Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
        }).start();
    }

    void mqttConnect(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                String clientId = "user"+System.currentTimeMillis(); //clientId很重要，不能重复，否则就会连不上，所以我定义成 app+当前时间
                try {
                    //实例化mqtt_client，填入我们定义的serverUri和clientId，然后MemoryPersistence设置clientid的保存形式，默认为以内存保存
                    Api.mqtt_client = new MqttClient(Api.mqttServer[0], clientId, new MemoryPersistence());
                    //创建并实例化一个MQTT的连接参数对象
                    MqttConnectOptions options = new MqttConnectOptions();
                    //然后设置对应的参数
                    options.setConnectionTimeout(30); // 设置超时时间，单位为秒
                    options.setKeepAliveInterval(30); //设置心跳,30s
                    options.setAutomaticReconnect(true); //是否重连
                    //设置是否清空session,设置为false表示服务器会保留客户端的连接记录，设置为true表示每次连接到服务器都以新的身份连接
                    options.setCleanSession(false);
                    //设置回调
                    Api.mqtt_client.setCallback(new MqttCallback() {
                        @Override
                        public void connectionLost(Throwable cause) {
                            //连接丢失后，一般在这里面进行重连

                        }
                        @Override
                        public void deliveryComplete(IMqttDeliveryToken token) {
                            //publish后会执行到这里
                        }
                        @Override
                        public void messageArrived(String topicName, MqttMessage message) {
                            //subscribe后得到的消息会执行到这里面
                            Log.d("MQTT消息到达！", topicName);
                            Log.d("MQTT消息到达！", message.toString());
                            if(topicName.equals("user"+uid)) //收到的是聊天记录
                                receive(message.toString());
                        }
                    });
                    //连接mqtt服务器
                    //Api.mqtt_client.connect();
                    if(!Api.mqtt_client.connectWithResult(options).getSessionPresent()) {
                        Api.mqtt_client.subscribe("user" + uid); //订阅的主题
                        Log.d("主活动","MQTT订阅成功！");
                    }
                    Log.d("MQTT服务", "连接成功！");
                }catch (Exception e) {
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, "连接MQTT服务器失败！！", Toast.LENGTH_LONG).show();
                        }
                    });
                }
            }
        }).start();
    }

    void receive(String message){  //接收消息，格式senderId|receiverId|ctime|var|senderNickname
        final String message_bak = message.replace("\n","\\n");
        byte[] temp = Base64.decode(message, Base64.URL_SAFE); //消息解密
        message = new String(temp);
        final String[] arr = message.split("\\|"); //解码消息
        arr[3] = new String(Base64.decode(arr[3], Base64.URL_SAFE)); //内容解密
        Log.d("解码结果", Arrays.toString(arr));
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    MyDatabaseHelper databaseHelper = new MyDatabaseHelper(MainActivity.this, "database.db", null, 1); //打开本地数据库
                    SQLiteDatabase db = databaseHelper.getWritableDatabase();
                    ContentValues values = new ContentValues(); //要添加到数据库中的数据
                    values.put("friend", arr[0]); //好友的id是发送者的id，数据包中的第一个参数是发送者ID
                    values.put("ctime", arr[2]);  //消息时间
                    values.put("var", arr[3]); //消息内容
                    values.put("state",1); //chat表中的state表示收消息
                    db.insert("chat",null,values);
                    values.clear();
                    values.put("state", 0); //标记未读                    //注意这里的的好友的id是传来的数据包里的uid
                    db.update("friend",values,"friend="+arr[0],null); //记得更新好友数据表，否则消息页不显示新消息

                    LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(MainActivity.this); //获取本地广播管理器实例
                    Intent intent = new Intent("cn.com.cnxfs.relaxchat.UPDATE_NEW_CHAT");
                    localBroadcastManager.sendBroadcast(intent); //发送广播通知news页面
                    intent = new Intent("cn.com.cnxfs.relaxchat.NEW_CHAT");
                    intent.putExtra("friend", Integer.parseInt(arr[0]));
                    intent.putExtra("ctime", arr[2]);
                    intent.putExtra("var", arr[3]);
                    intent.putExtra("senderNickname", arr[4]);
                    localBroadcastManager.sendBroadcast(intent); //发送广播通知chat页面
                    Log.d("主活动","接收离线消息成功！");

                    //从服务器端删除备份数据
                    String json = "{\"var\": \""+message_bak+"\"}";
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url(Api.url[0]+"/swap/del")
                            .post(RequestBody.create(MediaType.parse("application/json"),json))
                            .build();
                    Response response = client.newCall(request).execute(); //执行发送指令
                }catch (Exception e){
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this,"接收消息失败！请检查网络连接！",Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
        }).start();
    }

    void receiveOfflineMsg(){  //接受离线消息
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    FormBody.Builder params = new FormBody.Builder();
                    params.add("friend",uid); //添加url参数
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url(Api.url[0]+"/swap/receive").post(params.build())
                            .build();
                    Response response = client.newCall(request).execute(); //执行发送指令
                    String responseData = response.body().string();
                    JSONArray jsonArray = new JSONArray(responseData);
                    for(int i=0; i<jsonArray.length(); i++){
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        receive(jsonObject.getString("var"));
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, "接受离线消息失败！", Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
        }).start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {  //关闭MQTT连接
            Api.mqtt_client.close();
        } catch (MqttException e) {
            e.printStackTrace();
        }
        Log.d("主活动", "再见！");
    }
}
